package com.taskmanager.service;

import com.taskmanager.dao.TaskDao;
import com.taskmanager.dao.TimerDao;
import com.taskmanager.dto.TimeRecordResponse;
import com.taskmanager.dto.TimerStatistics;
import com.taskmanager.entity.TimeRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 计时器业务逻辑层
 */
@Service
public class TimerService {
    
    @Autowired
    private TimerDao timerDao;
    
    @Autowired
    private TaskDao taskDao;
    
    /**
     * 开始计时
     * @param userId 用户ID
     * @param taskId 任务ID
     * @return 计时记录响应
     */
    @Transactional(rollbackFor = Exception.class)
    public TimeRecordResponse startTimer(Long userId, Long taskId) {
        // 检查是否有正在运行的计时器
        TimeRecord currentTimer = timerDao.selectCurrentTimer(userId);
        if (currentTimer != null) {
            throw new IllegalStateException("已有正在运行的计时器，请先停止当前计时");
        }
        
        // 验证任务是否存在且属于该用户
        if (!taskDao.belongsToUser(taskId, userId)) {
            throw new IllegalArgumentException("任务不存在或无权访问");
        }
        
        // 创建新的计时记录
        TimeRecord record = new TimeRecord();
        record.setUserId(userId);
        record.setTaskId(taskId);
        record.setStartTime(LocalDateTime.now());
        record.setDuration(0);
        record.setStatus("RUNNING");
        
        int result = timerDao.insert(record);
        if (result <= 0) {
            throw new RuntimeException("创建计时记录失败");
        }
        
        // 查询完整信息并返回
        TimeRecord created = timerDao.selectByIdWithDetails(record.getRecordId());
        return convertToResponse(created);
    }
    
    /**
     * 暂停计时
     * @param recordId 记录ID
     * @param userId 用户ID
     * @return 计时记录响应
     */
    @Transactional(rollbackFor = Exception.class)
    public TimeRecordResponse pauseTimer(Long recordId, Long userId) {
        // 验证记录所有权
        if (!timerDao.belongsToUser(recordId, userId)) {
            throw new IllegalArgumentException("无权操作此计时记录");
        }
        
        TimeRecord record = timerDao.selectById(recordId);
        if (record == null) {
            throw new IllegalArgumentException("计时记录不存在");
        }
        
        if (!"RUNNING".equals(record.getStatus())) {
            throw new IllegalStateException("计时器未在运行中");
        }
        
        // 计算当前持续时长
        int currentDuration = calculateDuration(record.getStartTime(), LocalDateTime.now());
        
        // 更新状态为暂停
        int result = timerDao.updateStatus(recordId, "PAUSED", currentDuration);
        if (result <= 0) {
            throw new RuntimeException("暂停计时失败");
        }
        
        // 查询更新后的记录
        TimeRecord updated = timerDao.selectByIdWithDetails(recordId);
        return convertToResponse(updated);
    }
    
    /**
     * 继续计时
     * @param recordId 记录ID
     * @param userId 用户ID
     * @return 计时记录响应
     */
    @Transactional(rollbackFor = Exception.class)
    public TimeRecordResponse resumeTimer(Long recordId, Long userId) {
        // 验证记录所有权
        if (!timerDao.belongsToUser(recordId, userId)) {
            throw new IllegalArgumentException("无权操作此计时记录");
        }
        
        TimeRecord record = timerDao.selectById(recordId);
        if (record == null) {
            throw new IllegalArgumentException("计时记录不存在");
        }
        
        if (!"PAUSED".equals(record.getStatus())) {
            throw new IllegalStateException("计时器未处于暂停状态");
        }
        
        // 更新状态为运行中
        int result = timerDao.updateStatus(recordId, "RUNNING", record.getDuration());
        if (result <= 0) {
            throw new RuntimeException("继续计时失败");
        }
        
        // 查询更新后的记录
        TimeRecord updated = timerDao.selectByIdWithDetails(recordId);
        return convertToResponse(updated);
    }
    
    /**
     * 停止计时
     * @param recordId 记录ID
     * @param userId 用户ID
     * @return 计时记录响应
     */
    @Transactional(rollbackFor = Exception.class)
    public TimeRecordResponse stopTimer(Long recordId, Long userId) {
        // 验证记录所有权
        if (!timerDao.belongsToUser(recordId, userId)) {
            throw new IllegalArgumentException("无权操作此计时记录");
        }
        
        TimeRecord record = timerDao.selectById(recordId);
        if (record == null) {
            throw new IllegalArgumentException("计时记录不存在");
        }
        
        if ("COMPLETED".equals(record.getStatus())) {
            throw new IllegalStateException("计时器已停止");
        }
        
        // 计算最终持续时长
        LocalDateTime endTime = LocalDateTime.now();
        int finalDuration;
        
        if ("RUNNING".equals(record.getStatus())) {
            // 如果是运行中，计算从开始到现在的时长
            finalDuration = calculateDuration(record.getStartTime(), endTime);
        } else {
            // 如果是暂停状态，使用已记录的时长
            finalDuration = record.getDuration();
        }
        
        // 更新记录为已完成
        int result = timerDao.updateEndTimeAndDuration(recordId, endTime, finalDuration);
        if (result <= 0) {
            throw new RuntimeException("停止计时失败");
        }
        
        // 更新任务的总计时时长
        updateTaskTotalTime(record.getTaskId());
        
        // 查询更新后的记录
        TimeRecord updated = timerDao.selectByIdWithDetails(recordId);
        return convertToResponse(updated);
    }
    
    /**
     * 获取当前运行的计时器
     * @param userId 用户ID
     * @return 计时记录响应，如果没有则返回null
     */
    public TimeRecordResponse getCurrentTimer(Long userId) {
        TimeRecord record = timerDao.selectCurrentTimer(userId);
        if (record == null) {
            return null;
        }
        
        // 如果是运行中，计算实时时长
        if ("RUNNING".equals(record.getStatus())) {
            int currentDuration = calculateDuration(record.getStartTime(), LocalDateTime.now());
            record.setDuration(currentDuration);
        }
        
        return convertToResponse(record);
    }
    
    /**
     * 获取计时记录列表
     * @param userId 用户ID
     * @param taskId 任务ID（可选）
     * @param startDate 开始日期（可选）
     * @param endDate 结束日期（可选）
     * @return 计时记录列表
     */
    public List<TimeRecordResponse> getTimeRecords(Long userId, Long taskId, 
                                                   LocalDate startDate, LocalDate endDate) {
        List<TimeRecord> records = timerDao.selectByConditions(userId, taskId, startDate, endDate);
        
        return records.stream()
                .map(this::convertToResponse)
                .collect(Collectors.toList());
    }
    
    /**
     * 删除计时记录
     * @param recordId 记录ID
     * @param userId 用户ID
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteTimeRecord(Long recordId, Long userId) {
        // 验证记录所有权
        if (!timerDao.belongsToUser(recordId, userId)) {
            throw new IllegalArgumentException("无权操作此计时记录");
        }
        
        TimeRecord record = timerDao.selectById(recordId);
        if (record == null) {
            throw new IllegalArgumentException("计时记录不存在");
        }
        
        // 删除记录
        int result = timerDao.deleteById(recordId);
        if (result <= 0) {
            throw new RuntimeException("删除计时记录失败");
        }
        
        // 更新任务的总计时时长
        updateTaskTotalTime(record.getTaskId());
    }
    
    /**
     * 获取统计信息
     * @param userId 用户ID
     * @param period 统计周期：today, week, month
     * @return 统计信息
     */
    public TimerStatistics getStatistics(Long userId, String period) {
        TimerStatistics statistics = new TimerStatistics();
        
        // 今日总时长
        Integer todayTotal = timerDao.sumTodayDuration(userId);
        statistics.setTodayTotal(todayTotal != null ? todayTotal : 0);
        
        // 本周总时长
        Integer weekTotal = timerDao.sumWeekDuration(userId);
        statistics.setWeekTotal(weekTotal != null ? weekTotal : 0);
        
        // 本月总时长
        Integer monthTotal = timerDao.sumMonthDuration(userId);
        statistics.setMonthTotal(monthTotal != null ? monthTotal : 0);
        
        // 按分类统计
        LocalDate startDate = getStartDate(period);
        LocalDate endDate = LocalDate.now();
        
        List<Map<String, Object>> categoryData = timerDao.sumDurationByCategory(userId, startDate, endDate);
        Map<String, Integer> categoryBreakdown = new HashMap<>();
        for (Map<String, Object> item : categoryData) {
            String categoryName = (String) item.get("categoryName");
            Object durationObj = item.get("duration");
            Integer duration = durationObj != null ? ((Number) durationObj).intValue() : 0;
            categoryBreakdown.put(categoryName, duration);
        }
        statistics.setCategoryBreakdown(categoryBreakdown);
        
        // 每日记录
        List<Map<String, Object>> dailyData = timerDao.sumDurationByDate(userId, startDate, endDate);
        List<TimerStatistics.DailyRecord> dailyRecords = new ArrayList<>();
        for (Map<String, Object> item : dailyData) {
            String date = item.get("date").toString();
            Object durationObj = item.get("duration");
            Integer duration = durationObj != null ? ((Number) durationObj).intValue() : 0;
            dailyRecords.add(new TimerStatistics.DailyRecord(date, duration));
        }
        statistics.setDailyRecords(dailyRecords);
        
        return statistics;
    }
    
    /**
     * 更新任务的总计时时长
     * @param taskId 任务ID
     */
    private void updateTaskTotalTime(Long taskId) {
        Integer totalTime = timerDao.sumTaskDuration(taskId);
        if (totalTime == null) {
            totalTime = 0;
        }
        
        // 更新任务表的total_time字段
        taskDao.updateTotalTime(taskId, totalTime);
    }
    
    /**
     * 计算持续时长（秒）
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return 持续时长（秒）
     */
    private int calculateDuration(LocalDateTime startTime, LocalDateTime endTime) {
        Duration duration = Duration.between(startTime, endTime);
        return (int) duration.getSeconds();
    }
    
    /**
     * 根据周期获取开始日期
     * @param period 周期：today, week, month
     * @return 开始日期
     */
    private LocalDate getStartDate(String period) {
        LocalDate now = LocalDate.now();
        switch (period) {
            case "today":
                return now;
            case "week":
                return now.minusWeeks(1);
            case "month":
                return now.minusMonths(1);
            default:
                return now.minusWeeks(1);
        }
    }
    
    /**
     * 格式化持续时长
     * @param seconds 秒数
     * @return 格式化字符串（如：2小时30分钟）
     */
    private String formatDuration(int seconds) {
        int hours = seconds / 3600;
        int minutes = (seconds % 3600) / 60;
        int secs = seconds % 60;
        
        if (hours > 0) {
            return String.format("%d小时%d分钟", hours, minutes);
        } else if (minutes > 0) {
            return String.format("%d分钟%d秒", minutes, secs);
        } else {
            return String.format("%d秒", secs);
        }
    }
    
    /**
     * 将TimeRecord实体转换为TimeRecordResponse
     * @param record 计时记录实体
     * @return 计时记录响应DTO
     */
    private TimeRecordResponse convertToResponse(TimeRecord record) {
        TimeRecordResponse response = new TimeRecordResponse();
        response.setRecordId(record.getRecordId());
        response.setTaskId(record.getTaskId());
        response.setTaskTitle(record.getTaskTitle());
        response.setCategoryName(record.getCategoryName());
        response.setCategoryColor(record.getCategoryColor());
        response.setStartTime(record.getStartTime());
        response.setEndTime(record.getEndTime());
        response.setDuration(record.getDuration());
        response.setStatus(record.getStatus());
        response.setFormattedDuration(formatDuration(record.getDuration()));
        response.setCreatedAt(record.getCreatedAt());
        return response;
    }
    
    /**
     * 获取详细统计信息
     * @param userId 用户ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 统计汇总DTO
     */
    public com.taskmanager.dto.StatisticsSummaryDTO getDetailedStatistics(Long userId, LocalDate startDate, LocalDate endDate) {
        com.taskmanager.dto.StatisticsSummaryDTO summary = new com.taskmanager.dto.StatisticsSummaryDTO();
        
        // 获取总次数
        Integer totalSessions = timerDao.countTotalSessions(userId, startDate, endDate);
        summary.setTotalSessions(totalSessions != null ? totalSessions : 0);
        
        // 获取总时长
        Integer totalDuration = timerDao.sumTotalDuration(userId, startDate, endDate);
        summary.setTotalDuration(totalDuration != null ? totalDuration : 0);
        
        // 获取活跃天数
        Integer activeDays = timerDao.countActiveDays(userId, startDate, endDate);
        summary.setActiveDays(activeDays != null ? activeDays : 0);
        
        // 计算日均时长
        int avgDailyDuration = 0;
        if (activeDays != null && activeDays > 0) {
            avgDailyDuration = totalDuration / activeDays;
        }
        summary.setAvgDailyDuration(avgDailyDuration);
        
        // 获取当日数据
        Map<String, Object> todayStats = timerDao.getTodayStatistics(userId);
        com.taskmanager.dto.TodayDataDTO todayData = new com.taskmanager.dto.TodayDataDTO();
        todayData.setDate(LocalDate.now().toString());
        todayData.setSessions(todayStats.get("sessions") != null ? ((Number) todayStats.get("sessions")).intValue() : 0);
        todayData.setDuration(todayStats.get("duration") != null ? ((Number) todayStats.get("duration")).intValue() : 0);
        summary.setTodayData(todayData);
        
        return summary;
    }
    
    /**
     * 获取分类统计信息
     * @param userId 用户ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 分类统计列表
     */
    public List<com.taskmanager.dto.CategoryStatisticsDTO> getCategoryStatistics(Long userId, LocalDate startDate, LocalDate endDate) {
        List<Map<String, Object>> categoryData = timerDao.sumDurationByCategoryWithDetails(userId, startDate, endDate);
        
        // 计算总时长用于计算占比
        int totalDuration = 0;
        for (Map<String, Object> item : categoryData) {
            Object durationObj = item.get("duration");
            totalDuration += durationObj != null ? ((Number) durationObj).intValue() : 0;
        }
        
        // 转换为DTO并计算占比
        List<com.taskmanager.dto.CategoryStatisticsDTO> result = new ArrayList<>();
        for (Map<String, Object> item : categoryData) {
            com.taskmanager.dto.CategoryStatisticsDTO dto = new com.taskmanager.dto.CategoryStatisticsDTO();
            
            Object categoryIdObj = item.get("categoryId");
            dto.setCategoryId(categoryIdObj != null ? ((Number) categoryIdObj).longValue() : null);
            dto.setCategoryName((String) item.get("categoryName"));
            dto.setCategoryColor((String) item.get("categoryColor"));
            
            Object sessionsObj = item.get("sessions");
            dto.setSessions(sessionsObj != null ? ((Number) sessionsObj).intValue() : 0);
            
            Object durationObj = item.get("duration");
            int duration = durationObj != null ? ((Number) durationObj).intValue() : 0;
            dto.setDuration(duration);
            
            // 计算占比
            double percentage = totalDuration > 0 ? (duration * 100.0 / totalDuration) : 0.0;
            dto.setPercentage(Math.round(percentage * 100.0) / 100.0); // 保留两位小数
            
            result.add(dto);
        }
        
        return result;
    }
    
    /**
     * 获取每日趋势统计
     * @param userId 用户ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return 每日趋势列表
     */
    public List<com.taskmanager.dto.DailyTrendDTO> getDailyTrendStatistics(Long userId, LocalDate startDate, LocalDate endDate) {
        List<Map<String, Object>> dailyData = timerDao.sumDurationByDateWithSessions(userId, startDate, endDate);
        
        List<com.taskmanager.dto.DailyTrendDTO> result = new ArrayList<>();
        for (Map<String, Object> item : dailyData) {
            com.taskmanager.dto.DailyTrendDTO dto = new com.taskmanager.dto.DailyTrendDTO();
            dto.setDate(item.get("date").toString());
            
            Object sessionsObj = item.get("sessions");
            dto.setSessions(sessionsObj != null ? ((Number) sessionsObj).intValue() : 0);
            
            Object durationObj = item.get("duration");
            dto.setDuration(durationObj != null ? ((Number) durationObj).intValue() : 0);
            
            result.add(dto);
        }
        
        return result;
    }
    
    /**
     * 导出统计数据为CSV
     * @param userId 用户ID
     * @param startDate 开始日期
     * @param endDate 结束日期
     * @return CSV格式字符串
     */
    public String exportStatisticsData(Long userId, LocalDate startDate, LocalDate endDate) {
        List<TimeRecord> records = timerDao.selectByConditions(userId, null, startDate, endDate);
        
        StringBuilder csv = new StringBuilder();
        // CSV头部
        csv.append("日期,任务,分类,开始时间,结束时间,时长(分钟)\n");
        
        // CSV数据行
        for (TimeRecord record : records) {
            if (!"COMPLETED".equals(record.getStatus())) {
                continue; // 只导出已完成的记录
            }
            
            csv.append(record.getStartTime().toLocalDate().toString()).append(",");
            csv.append(escapeCSV(record.getTaskTitle())).append(",");
            csv.append(escapeCSV(record.getCategoryName() != null ? record.getCategoryName() : "未分类")).append(",");
            csv.append(record.getStartTime().toLocalTime().toString()).append(",");
            csv.append(record.getEndTime() != null ? record.getEndTime().toLocalTime().toString() : "").append(",");
            csv.append(record.getDuration() / 60).append("\n"); // 转换为分钟
        }
        
        return csv.toString();
    }
    
    /**
     * 转义CSV字段中的特殊字符
     * @param value 原始值
     * @return 转义后的值
     */
    private String escapeCSV(String value) {
        if (value == null) {
            return "";
        }
        if (value.contains(",") || value.contains("\"") || value.contains("\n")) {
            return "\"" + value.replace("\"", "\"\"") + "\"";
        }
        return value;
    }
}
